Add runtime detection for toResizableBuffer#27096
Conversation
4a2b43f to
11fb3c6
Compare
A nice thing about emscripten/system/lib/standalone/standalone.c Lines 138 to 141 in d1fbb02 It also skips the emscripten/tools/acorn-optimizer.mjs Lines 1081 to 1084 in d1fbb02 Thinking about this more, since emscripten/tools/feature_matrix.py Lines 143 to 151 in d1fbb02 |
|
Yes, GROWABLE_ARRAYBUFFERS should certainly be auto-enabled when the feature matrix allows is. If that isn't the case today we should fix that. |
1ef543f to
70630b5
Compare
70630b5 to
7df7165
Compare
7df7165 to
2781f78
Compare
2781f78 to
e6316ef
Compare
bda5ef7 to
6b6a0c6
Compare
…allow (#27097) See #27096 (comment) Also, remove the experimental status, since this feature is now available in all browser and we hope to feature-detect it soon and start using it even without this flag. Fixes: #26099
86aa197 to
95d431f
Compare
|
I think this change should be good to go now. PTAL. |
| // and Node.js. | ||
| // and Node.js. Even when this setting is disabled, Emscripten will still use this | ||
| // feature when available, but it include the fall back code for handling | ||
| // non-growable memories. |
There was a problem hiding this comment.
Perhaps explain why? We don't do this with other features afaik?
There was a problem hiding this comment.
I think we do do feature detection in some places.
The reason we want both approaches in this case is kind of important. There are two main cases:
-
For all users or pthreads+memory growth we probably want to use
toResizableBufferwhen available in all cases. It slightly fast since we don't need to rebuild the views each time the memory grows. There is very little cost to probing for, and using the features if its found. -
For users that know that they are only targetting newer browsers they can opt in with
-sGROWABLE_ARRAYBUFFERSwhich means we don't need run the wholegrowableHeapJS optimizer path (which is the thing that slows down all the HEAP accesses in normal builder). These users see even more of a benefit, but their code won't run on older browsers.
There was a problem hiding this comment.
For example of where we do feature detection you can see many by doing git grep "if .*globalThis" src.
In most cases we don't have setting to opt out of the feature-detection and just assume the feature is present. In some cases we can use the feature matrix to detect when the feature-detection is not needed.
In the long run I think we may just want to delete this setting (or at least make it internal) since it can be driven completely by the feature matrix.
There was a problem hiding this comment.
For example of where we do feature detection you can see many by doing git grep "if .*globalThis" src.
Do we have feature flags for those things, though? E.g. one result is
src/lib/libembind.js: if (!globalThis.FinalizationRegistry) {
I don't think we have a flag for that, so we have to check it.
That is, what seems new to me is Even when this setting is disabled, Emscripten will still use this feature when available - do we do that anywhere else? Normally if a user disables a setting, we don't use the feature, afaik
There was a problem hiding this comment.
For this feature I think we want two things:
- We want to use it whenever we can. There is really no need to be able to completely opt out. (just like with
FinalizationRegistry). - We want to be able to create a built where we assume its always present (because we want to be able to opt out of the cost of using
growableHeapJS transform.
We maybe its not something we have done before (both features detection and a setting). But I certainly think its justified in this case.
Unless you have any other ideas about how to better take advantage of this by default?
There was a problem hiding this comment.
Maybe I'm over excited about not having to ever re-create the memory views. Given that modern browsers can avoid it, it just seems ergonomic to do it.
It also has some other nice side benefits like if users store memory views anywhere or pass them around the they continue to work and grow. Right now any such stored view will be broken on memory growth.
I guess its just seems like such nice simplification to me, but you are right that it comes with a small code size hit.
There was a problem hiding this comment.
I'm also hoping we can simply remove the emscripten_notify_memory_growth mechanism that we have in place to support PUSE_WASI.. maybe maybe we should just remove the PURE_WASI stuff instead?
There was a problem hiding this comment.
Yeah, I guess I am not sure if this is worth the benefit or not. I can see arguments both ways. Definitely this avoids some bugs in user JS code, as you say... Have we seen users hit such bugs, do you remember?
There was a problem hiding this comment.
About PURE_WASI, maybe we can make that mode not support JS, that is, pure WASI only runs in WASI environments? It is supporting pure WASI in JS that makes things hard and need that growth callback.
There was a problem hiding this comment.
Part of my original idea for PURE_WASI was that you could do ./emcc -sPURE_WASI --post-link <some_file>.wasm as a way to run the wasi file on the web.
That never really panned out though.
95d431f to
a65cb5c
Compare
5988ea6 to
46fcff4
Compare
46fcff4 to
18b2604
Compare
18b2604 to
916a95e
Compare
|
I've rephrased both the ChangeLog entry and the settings documentation to better describe the default behaviour and why you might still want to opt in using the explicit settings. |
331ee95 to
4aba359
Compare
Since this feature is now supported by all major browsers, we want to take advantage of it whenever possible to improve memory growth efficiency. We keep the `GROWABLE_ARRAYBUFFERS` compile-time setting to allow forcing its use and removing the fallback code, which saves some code size and avoids runtime checks. Fixes emscripten-core#27084
4aba359 to
6f35636
Compare
| return wasmMemory.toResizableBuffer(); | ||
| #else | ||
| #if SHARED_MEMORY && (MIN_FIREFOX_VERSION != TARGET_NOT_SUPPORTED) | ||
| // Using `toResizableBuffer` on a shared memory is currently broken on Firefox |
There was a problem hiding this comment.
Reading the below Firefox bug report, I think this comment should be adjusted to something like:
| // Using `toResizableBuffer` on a shared memory is currently broken on Firefox | |
| // Deserializing a growable SharedArrayBuffer is currently broken in Firefox. |
(i.e. wasmMemory.toResizableBuffer() works as expected, but it cannot be deserialized in web workers.)
| // Note that Emscripten will always take advantage of this feature when it is | ||
| // available, regardless of this setting. Enabling this setting effectively | ||
| // removes the fallback code (which adds overhead in multi-threaded builds). | ||
| // Only enable this setting if you know that all of your target browser | ||
| // engines support this feature. |
There was a problem hiding this comment.
How about turning this into a three-mode setting, similar to -sTEXTDECODER? That would give us:
-sGROWABLE_ARRAYBUFFERS=0- current default: the generated code will not use a growableSharedArrayBuffer.-sGROWABLE_ARRAYBUFFERS=1- potential new default: the generated code will use a growableSharedArrayBufferwhen available and supported.-sGROWABLE_ARRAYBUFFERS=2- assumes theWebAssembly.Memory.toResizableBuffer() APIis available and usable and omits any JS fallback code.
There was a problem hiding this comment.
Oh sorry, I just noticed this is also mentioned in #27096 (comment).
There was a problem hiding this comment.
Good idea. Lets do that.
There was a problem hiding this comment.
BTW, we default to =1 for TEXTDECODER, which means "feature detect with fallback", so this is great analogy to what we have here.
Since this is now shipping in the current version of all major browsers
we want to take advantage of it whenever possible.
See the ChangeLog entry and docs for why it still makes sense to keep
the explicit
GROWABLE_ARRAYBUFFERSsetting around (at least fornow).
As a side effect this change also works around #27084.